package org.jkuang.qstar.index.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.jkuang.qstar.commons.jni.CurMap;
import org.jkuang.qstar.index.cmp.IndexObject;
import org.jkuang.qstar.index.cmp.SortComparator;
import org.jkuang.qstar.index.core.IndexReader.QueryArg;
import org.jkuang.qstar.index.dic.TermsDic;
import org.jkuang.qstar.index.filter.QueryFilter;
import org.jkuang.qstar.index.filter.RepeatFilter;
import org.jkuang.qstar.index.filter.ResultFilter;
import org.jkuang.qstar.index.iterator.NodeFilter;
import org.jkuang.qstar.index.iterator.QueryStatus;
import org.jkuang.qstar.index.iterator.TSQueue;
import org.jkuang.qstar.index.parser.ParserParam;
import org.jkuang.qstar.index.parser.SyntaxParser;
import org.jkuang.qstar.index.store.DataNode;
import org.jkuang.qstar.index.store.DataStruct;

/**
 * 执行扫描
 * 
 * @author jkuang 2012年11月17日
 *
 */
public class QueryExecuter {
	private boolean isDebug;
	private TermsDic dic;
	private CurMap store;
	private ReentrantReadWriteLock rwlock;
	private DataStruct<IndexObject> indexs;
	private SortComparator comparator = new SortComparator();

	public QueryExecuter(TermsDic dic, ReentrantReadWriteLock rwlock, DataStruct<IndexObject> indexs, CurMap store) {
		this.dic = dic;
		this.rwlock = rwlock;
		this.indexs = indexs;
		this.store = store;
	}

	/**
	 * 统计该条件下最坏情况下的扫描数量
	 * 
	 * @param filter
	 * @param _s_sort_
	 * @param _e_sort_
	 * @param indexSizes
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private int scanSize(Set<Integer> filter, DataNode _s_sort_, DataNode _e_sort_, Map<Integer, Integer> indexSizes) {
		int scansize = -1;
		int minIndex = -1;
		IndexObject tempStruct = new IndexObject();
		for (Integer i : filter) {
			int size = 0;
			if (indexSizes.containsKey(i)) {
				size = indexSizes.get(i);
			} else {
				DataStruct<DataNode> index = (DataStruct<DataNode>) this.indexs.get(tempStruct.setIndex(i));
				if (index != null) {
					size = index.scanSize(_s_sort_, _e_sort_);
					indexSizes.put(i, size);
				} else {
					indexSizes.put(i, 0);
					return i;
				}
			}
			if (scansize == -1 || size < scansize) {
				minIndex = i;
				scansize = size;
			}
		}
		return minIndex;
	}

	/**
	 * 统计该条件下的最坏扫描总量
	 * 
	 * @param list
	 * @param _s_sort_
	 * @param _e_sort_
	 * @param indexSizes
	 * @param indexIterator
	 * @return
	 */
	private int scanSize(List<Set<Integer>> list, DataNode _s_sort_, DataNode _e_sort_,
			Map<Integer, Integer> indexSizes, Map<Integer, List<Set<Integer>>> indexIterator) {
		int sum = 0;
		for (Set<Integer> filter : list) {

			int index = scanSize(filter, _s_sort_, _e_sort_, indexSizes);
			int indexsize = indexSizes.get(index);
			if (indexsize > 0) {
				if (indexIterator.containsKey(index)) {
					indexIterator.get(index).add(filter);
				} else {
					sum += indexsize;
					List<Set<Integer>> values = new ArrayList<>();
					values.add(filter);
					indexIterator.put(index, values);
				}
			}
		}
		return sum;
	}

	/**
	 * 打印语法分析拆分后的串
	 * 
	 * @param indexIterator
	 * @param vlm
	 */
	private void print(Map<Integer, List<Set<Integer>>> indexIterator, Map<Integer, Integer> vlm) {
		for (Integer key : indexIterator.keySet()) {
			StringBuffer buffer = new StringBuffer();
			buffer.append(dic.get(key)).append("--->").append(vlm.get(key)).append(" sub:");
			List<Set<Integer>> values = indexIterator.get(key);
			for (int i = 0; i < values.size(); i++) {
				if (values.get(i).size() == 1) {
					buffer.delete(0, buffer.length());
					break;
				}
				StringBuffer temp = new StringBuffer();
				for (Integer v : values.get(i)) {
					if (v.intValue() == key.intValue()) {
						continue;
					} else if (temp.length() > 0) {
						temp.append(" AND ");
					}
					temp.append(dic.get(v)).append("->").append(vlm.get(v));
				}
				if (temp.length() == 0) {
					continue;
				}
				if (i > 0) {
					buffer.append(" OR (");
				} else {
					buffer.append(" (");
				}
				buffer.append(temp);
				buffer.append(")");
			}
			System.out.println(buffer);
		}
	}

	@SuppressWarnings("unchecked")
	private void addTSIterator(TSQueue<DataNode> queue, Map<Integer, List<Set<Integer>>> indexIterator,
			List<Set<Integer>> filterValues, DataNode _s_sort_, DataNode _e_sort_, boolean desc) {
		IndexObject tempStruct = new IndexObject();
		for (Map.Entry<Integer, List<Set<Integer>>> entry : indexIterator.entrySet()) {
			int keyIndex = entry.getKey();
			List<Set<Integer>> filter = entry.getValue();
			for (Set<Integer> fSet : filter) {
				if (fSet.size() == 1) {
					filter.clear();
					break;
				} else {
					fSet.remove(keyIndex);
				}
			}
			DataStruct<DataNode> index = (DataStruct<DataNode>) indexs.get(tempStruct.setIndex(keyIndex));
			if (index != null) {
				queue.add(index.blockList(_s_sort_, _e_sort_, desc, new NodeFilter(filter, filterValues)));
			}
		}
	}

	/**
	 * 生成语法迭代器
	 * 
	 * @param syntax
	 * @param _s_sort_
	 * @param _e_sort_
	 * @param desc
	 * @return
	 */
	TSQueue<DataNode> createTSQueue(String syntax, DataNode _s_sort_, DataNode _e_sort_, boolean desc) {
		SyntaxParser parser = new SyntaxParser(dic);
		long time0 = System.currentTimeMillis();
		ParserParam param = parser.parser(syntax);
		long time1 = System.currentTimeMillis();
		Map<Integer, Integer> indexSize = new TreeMap<>();

		Map<Integer, List<Set<Integer>>> indexIterator0 = new HashMap<>();
		Map<Integer, List<Set<Integer>>> indexIterator1 = new HashMap<>();

		// 统计第一部分扫描代价
		int scanNum0 = this.scanSize(param.getResult(), _s_sort_, _e_sort_, indexSize, indexIterator0);
		// 统计第二部分扫描代价
		int scanNum1 = this.scanSize(param.getFilter(), _s_sort_, _e_sort_, indexSize, indexIterator1);
		long time2 = System.currentTimeMillis();
		TSQueue<DataNode> queue = new TSQueue<DataNode>(16, comparator, desc);

		if (isDebug) {
			for (Integer index : indexSize.keySet()) {
				System.out.println(dic.get(index) + " size is " + indexSize.get(index));
			}
			if (param.getFilter().size() > 0 && scanNum0 > scanNum1) {
				print(indexIterator1, indexSize);
			} else {
				print(indexIterator0, indexSize);
			}
		}
		long time3 = System.currentTimeMillis();
		// 如果第二部分的代码的扫描代价小于第一部分的扫描代价，则将第一部分做为过滤，直接扫描第二部分
		if (param.getFilter().size() > 0 && scanNum0 > scanNum1) {
			addTSIterator(queue, indexIterator1, param.getResult(), _s_sort_, _e_sort_, desc);
		} else {
			addTSIterator(queue, indexIterator0, param.getFilter(), _s_sort_, _e_sort_, desc);
		}
		long time4 = System.currentTimeMillis();
		if (isDebug) {
			System.out.println("parser cost:" + (time1 - time0) + "ms");
			System.out.println("scanSize cost:" + (time2 - time1) + "ms");
			System.out.println("add queue cost:" + (time4 - time3) + "ms");
		}
		return queue;
	}

	/**
	 * 执行运算，获取数据
	 * 
	 * @param queue
	 * @param status
	 * @param filter
	 * @return
	 */
	private QueryStatus<DataNode> execute(TSQueue<DataNode> queue, QueryStatus<DataNode> status) {
		ResultFilter rfilter = status.getRFilter();
		QueryFilter  qfilter = status.getQFilter();
		while ((status.isGetCount() || !status.pageFull()) && queue.hasNext()) {
			DataNode node = queue.next();
			if(qfilter==null || qfilter.accept(node, dic, store))
			{
				if (!status.pageFull() && status.startAddNode() && (rfilter == null || rfilter.accept(node, dic, store))) {
					status.addNode(node);
				}
				status.next();
			}
		}
		return status;
	}

	/**
	 * 
	 * @param syntax   统一的语法取前n条
	 * @param _s_sort_
	 * @param _e_sort_
	 * @param desc
	 * @param status
	 * @param filter
	 * @return
	 */
	QueryStatus<DataNode> execute(String syntax, DataNode _s_sort_, DataNode _e_sort_, boolean desc,
			QueryStatus<DataNode> status) {
		try {
			rwlock.readLock().lock();
			TSQueue<DataNode> queue = createTSQueue(syntax, _s_sort_, _e_sort_, desc);
			return execute(queue, status);
		} finally {
			rwlock.readLock().unlock();
		}
	}

	/**
	 * 批量获取各自条件的数据
	 * 
	 * @param args
	 * @param desc
	 * @return
	 */
	Map<QueryArg, QueryStatus<DataNode>> execute(List<QueryArg> args, int rows, int count, boolean desc) {
		try {
			Map<QueryArg, QueryStatus<DataNode>> map = new LinkedHashMap<>();
			rwlock.readLock().lock();
			for (QueryArg arg : args) {
				TSQueue<DataNode> queue = createTSQueue(arg.syntax, arg._s_sort_, arg._e_sort_, desc);
				QueryStatus<DataNode> status = new QueryStatus<>(0, rows, count,null, new RepeatFilter());
				map.put(arg, execute(queue, status));
			}
			return map;
		} finally {
			rwlock.readLock().unlock();
		}
	}

	/**
	 * 批量多条件混合排序（各自不同的条件混排，取前N条）
	 * 
	 * @param args
	 * @param desc
	 * @param status
	 * @param filter
	 * @return
	 */
	QueryStatus<DataNode> execute(List<QueryArg> args, boolean desc, QueryStatus<DataNode> status) {
		try {
			rwlock.readLock().lock();
			TSQueue<DataNode> queue = new TSQueue<DataNode>(args.size(), comparator, desc);
			for (QueryArg arg:args) {
				TSQueue<DataNode> temp = createTSQueue(arg.syntax, arg._s_sort_, arg._e_sort_, desc);
				if (temp.hasNext()) {
					queue.add(temp);
				}
			}
			return execute(queue, status);
		} finally {
			rwlock.readLock().unlock();
		}
	}
}
